package com.inspur.edp.common.expr.visitor;

import com.inspur.edp.common.expr.ast.CompileUnitParser;
import com.inspur.edp.common.expr.exception.ExpressException;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lizhaorui
 * @date 2025/8/18
 * @description
 */
public class StatementVisitor {

    private static StatementVisitor instance;

    private Map<Class, StatementInternalVisitor> visitMap = new HashMap<>();

    public static StatementVisitor getInstance() {
        if (instance == null) {
            synchronized (StatementVisitor.class) {
                if (instance == null) {
                    StatementVisitor temp = new StatementVisitor();
                    temp.visitMap.put(CompileUnitParser.ExprStatementContext.class, new ExprStatement());
                    temp.visitMap.put(CompileUnitParser.SuperStatementContext.class, new SuperStatement());
                    temp.visitMap.put(CompileUnitParser.EmptyStatementContext.class, new EmptyStatement());
                    temp.visitMap.put(CompileUnitParser.ForStatementContext.class, new ForStatement());
                    temp.visitMap.put(CompileUnitParser.ForEachStatementContext.class, new ForEachStatement());
                    temp.visitMap.put(CompileUnitParser.WhileStatementContext.class, new WhileStatement());
                    temp.visitMap.put(CompileUnitParser.BreakStatementContext.class, new BreakStatement());
                    temp.visitMap.put(CompileUnitParser.SwitchStatementContext.class, new SwitchStatement());
                    temp.visitMap.put(CompileUnitParser.SelectStatementContext.class, new SelectStatement());
                    temp.visitMap.put(CompileUnitParser.ContinueStatementContext.class, new ContinueStatement());
                    temp.visitMap.put(CompileUnitParser.ReturnStatementContext.class, new ReturnStatement());
                    temp.visitMap.put(CompileUnitParser.ThrowStatementContext.class, new ThrowStatement());
                    temp.visitMap.put(CompileUnitParser.TryCatchFinallyStatementContext.class, new TryCatchStatement());
                    instance = temp;
                }
            }
        }
        return instance;
    }

    interface StatementInternalVisitor {
        String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor);
    }

    public static String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
        StatementVisitor manager = StatementVisitor.getInstance();
        Class cls = ctx.getClass();
        if (manager.visitMap.containsKey(cls)) {
            StatementInternalVisitor visitor = manager.visitMap.get(cls);
            return visitor.visit(ctx, compileUnitVisitor);
        } else {
            throw new ExpressException("not support primitive type " + cls.getName());
        }
    }

    static class ExprStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            CompileUnitParser.ExpressContext expressContext = ((CompileUnitParser.ExprStatementContext) ctx).express();
            String exprCode = ExpressVisitManager.visit(compileUnitVisitor,expressContext).toString();
            return exprCode + ";";
        }
    }

    static class SuperStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitSuperStatement((CompileUnitParser.SuperStatementContext) ctx) + ";";
        }
    }

    static class EmptyStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitEmptyStatement((CompileUnitParser.EmptyStatementContext) ctx) + ";";
        }
    }

    static class ForStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitForStatement((CompileUnitParser.ForStatementContext) ctx) + ";";
        }
    }

    static class ForEachStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitForEachStatement((CompileUnitParser.ForEachStatementContext) ctx).toString();
        }
    }

    static class WhileStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitWhileStatement((CompileUnitParser.WhileStatementContext) ctx) + ";";
        }
    }

    static class BreakStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitBreakStatement((CompileUnitParser.BreakStatementContext) ctx) + ";";
        }
    }

    static class SwitchStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitSwitchStatement((CompileUnitParser.SwitchStatementContext) ctx).toString();
        }
    }

    static class SelectStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitSelectStatement((CompileUnitParser.SelectStatementContext) ctx).toString();
        }
    }

    static class ContinueStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitContinueStatement((CompileUnitParser.ContinueStatementContext) ctx) + ";";
        }
    }

    static class ReturnStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitReturnStatement((CompileUnitParser.ReturnStatementContext) ctx) + ";";
        }
    }

    static class ThrowStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitThrowStatement((CompileUnitParser.ThrowStatementContext) ctx) + ";";
        }
    }

    static class TryCatchStatement implements StatementInternalVisitor {

        @Override
        public String visit(CompileUnitParser.StatementContext ctx, JavaVisitor compileUnitVisitor) {
            return compileUnitVisitor.visitTryCatchFinallyStatement((CompileUnitParser.TryCatchFinallyStatementContext) ctx) + ";";
        }
    }

}